using System;
using System.Collections.Generic;
using System.Linq;

using Holdem.Interfaces.ReplayEngine;
using Holdem.Interfaces.Service;
using Holdem.Service.Modules;

using Ninject;

namespace Holdem.Service
{
	public sealed class Factory : IFactory, IReplayEngineHost
    {
        private static Factory _instance = new Factory();
        private static StandardKernel _kernel;
		private static IList<string> _engineNames;


        private Factory()
        {
            this.BindInjectors();
        }

        //~Factory()
        //{
            
        //}

        private void BindInjectors()
        {
            if (_kernel != null)
                return;

            _kernel = new StandardKernel(
				new HoldemServiceFactoryInjector(),
                new HoldemCardThemeInjector(),
                new HoldemServiceCommonInjector(),
				new HoldemReplayEngineProviderInjector(this),
				new HoldemModelInjector(),
                new HoldemViewModelInjector());


            //_kernel.Components.Add<IInjectionHeuristic, Heuristic>();

            //var config = _kernel.Get<IReplayEngine>();
        }

        //public class Heuristic : IInjectionHeuristic
        //{
        //    #region Implementation of IDisposable

        //    public void Dispose()
        //    {
                
        //    }

        //    #endregion

        //    #region Implementation of INinjectComponent

        //    public INinjectSettings Settings { get; set; }

        //    public bool ShouldInject(MemberInfo member)
        //    {
        //        var memberH = member.MemberType == MemberTypes.Constructor;

        //        return memberH;
        //    }

        //    #endregion
        //}

        public static Factory Instance
        {
            get
            {
                return _instance ?? (_instance = new Factory());
            }
        }

        //public void Dispose()
        //{
        //    if (DesignerProperties.IsInDesignTool)
        //        return;

        //    this.Dispose(true);
        //    GC.SuppressFinalize(this);
        //}

        //private void Dispose(bool disposing)
        //{
        //    if( !disposing || _kernel.IsDisposed )
        //        return;
        //    if (_kernel != null)
        //        _kernel.Dispose();
        //}

		#region IReplayEngineHost

		public IEnumerable<IReplayEngine> ReplayEngines
		{
            get { return _kernel.GetAll<IReplayEngine>(); }
		}

		public IEnumerable<string> EngineNames
		{
			get
			{
				if (_engineNames == null || !_engineNames.Any())
					_engineNames = new List<string>(this.ReplayEngines.Select(x => x.DisplayName).Distinct());

				return _engineNames;
			}
		}

		#endregion //IReplayEngineHost

		#region Implementation of IServiceLocator

		/// <summary>
		/// Gets the service object of the specified type.
		/// </summary>
		/// <returns>
		/// A service object of type <paramref name="serviceType"/>.-or- null if there is no service object of type <paramref name="serviceType"/>.
		/// </returns>
		/// <param name="serviceType">An object that specifies the type of service object to get. </param>
		public object GetService(Type serviceType)
		{
			return _kernel.Get(serviceType);
		}

		/// <summary>
		/// Get an instance of the given <paramref name="serviceType"/>.
		/// </summary>
		/// <param name="serviceType">Type of object requested.</param><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is an error resolving
		///             the service instance.</exception>
		/// <returns>
		/// The requested service instance.
		/// </returns>
		public object GetInstance(Type serviceType)
		{
			return _kernel.Get(serviceType);
		}

		/// <summary>
		/// Get an instance of the given named <paramref name="serviceType"/>.
		/// </summary>
		/// <param name="serviceType">Type of object requested.</param><param name="key">Name the object was registered with.</param><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is an error resolving
		///             the service instance.</exception>
		/// <returns>
		/// The requested service instance.
		/// </returns>
		public object GetInstance(Type serviceType, string key)
		{
			return _kernel.Get(serviceType, key);
		}

		/// <summary>
		/// Get all instances of the given <paramref name="serviceType"/> currently
		///             registered in the container.
		/// </summary>
		/// <param name="serviceType">Type of object requested.</param><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is are errors resolving
		///             the service instance.</exception>
		/// <returns>
		/// A sequence of instances of the requested <paramref name="serviceType"/>.
		/// </returns>
		public IEnumerable<object> GetAllInstances(Type serviceType)
		{
			return _kernel.GetAll(serviceType);
		}

		/// <summary>
		/// Get an instance of the given <typeparamref name="TService"/>.
		/// </summary>
		/// <typeparam name="TService">Type of object requested.</typeparam><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is are errors resolving
		///             the service instance.</exception>
		/// <returns>
		/// The requested service instance.
		/// </returns>
		public TService GetInstance<TService>()
		{
            return _kernel.Get<TService>();
		}

		/// <summary>
		/// Get an instance of the given named <typeparamref name="TService"/>.
		/// </summary>
		/// <typeparam name="TService">Type of object requested.</typeparam><param name="key">Name the object was registered with.</param><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is are errors resolving
		///             the service instance.</exception>
		/// <returns>
		/// The requested service instance.
		/// </returns>
		public TService GetInstance<TService>(string key)
		{
			return _kernel.Get<TService>(key);
		}

		/// <summary>
		/// Get all instances of the given <typeparamref name="TService"/> currently
		///             registered in the container.
		/// </summary>
		/// <typeparam name="TService">Type of object requested.</typeparam><exception cref="T:Microsoft.Practices.ServiceLocation.ActivationException">if there is are errors resolving
		///             the service instance.</exception>
		/// <returns>
		/// A sequence of instances of the requested <typeparamref name="TService"/>.
		/// </returns>
		public IEnumerable<TService> GetAllInstances<TService>()
		{
			return _kernel.GetAll<TService>();
		}

		#endregion
    }
}